/**
 * edurender
 * ersw_main.c
 * (c) 2009 J. Brad Byrd
 */

#include "ersw_texture.h"

#include "../er/er_assert.h"
#include "../er/er_memory.h"
#include "../er/er_math.h"

#include <stdlib.h>
#include <string.h>

static const ERuint s_formatBytes[] =
{
	3,
	4,
};	

ERSWTexture2D *erswCreateTexture2D(ERushort width, ERushort height, ERFormat format)
{
	ERSWTexture2D *t;
	
	t = (ERSWTexture2D *)ER_MALLOC(sizeof(ERSWTexture2D));

	t->width = width;
	t->height = height;
	t->mips = 0;
	t->format = format;

	while (width > 1 && height > 1)
	{
		t->texels[t->mips] = ER_MALLOC(width * height * s_formatBytes[format]);
		ER_ASSERT(t->texels[t->mips]);
		t->mips++;
		
		width >>= 1;
		height >>= 1;
		
		if (width == 0)
			width = 1;
			
		if (height == 0)
			height = 1;
	}

	return t;
}

void erswDestroyTexture2D(ERSWTexture2D *texture)
{
	int i;
	
	ER_ASSERT(texture);
	
	for (i = 0; i < texture->mips; i++)
		ER_FREE(texture->texels[i]);
		
	ER_FREE(texture);
}

void erswTexture2DUpload(ERSWTexture2D *texture, ERushort mip, const void *texels)
{
	ERuint width;
	ERuint height;
	
	ER_ASSERT(texture);
	
	width = texture->width >> mip;
	height = texture->height >> mip;
	
	memcpy(texture->texels[mip], texels, width * height * s_formatBytes[texture->format]);
}

ERRgbaColor erswTexture2DSample(const ERSWTexture2D *texture, const ERSWSampler *sampler,
	ERint u, ERint v)
{
	ERRgbaColor output = {255, 255, 255, 255};
	ERuint x, y;
	
	if (texture == NULL)
		return output;
	
	// Hardcode to repeat wrap and nearest filtering.
	//x = (((texture->width * u) + 0x7F) >> 8) & (texture->width - 1);
	//y = (((texture->height * v) + 0x7F) >> 8) & (texture->height - 1);

	//x = (u & (texture->width - 1)) * texture->width; 
	//y = (v & (texture->height - 1)) * texture->height; 

	//x = (u & 0xFFFF) >> 13;
	//y = (v & 0xFFFF) >> 13;

	x = (u >> 24) & 0x7;
	y = (v >> 24) & 0x7;

	output = ((ERRgbaColor *)texture->texels[0])[y * texture->width + x];
	
	return output;
}
